package gui;

import processing.core.*;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

public class GUI {
	// GUI class that stores a list of widgets, a HashMap of fonts,
	// handles user input events, causes widgets to update state, 
	// and operates as a factory class to create new widgets
	
	private final PApplet pa;
	private LinkedList<Widget> widgets;
	private HashMap<String, PFont> fonts;
	private int backgroundColor;
	
	public GUI(PApplet inputPA, HashMap<String, String> initFonts, int backgroundColor) {
		// Store the processing applet
		pa = inputPA;
		
		// Initialise the widget list
		widgets = new LinkedList<Widget>();
		
		// Initialise the GUI fonts
		initializeFonts(initFonts);
		
		this.backgroundColor = backgroundColor;
	}

	private void initializeFonts(HashMap<String, String> initFonts) {		
	    fonts = new HashMap<String, PFont>();
	    
	    for (Map.Entry<String, String> font : initFonts.entrySet()) {
			fonts.put(font.getKey(), pa.loadFont(font.getValue()));	    	
	    }

	}
	
	public void setFont(String shortFontName) {
	    pa.textFont( (PFont) fonts.get(shortFontName) );
	}

	public void draw() {
		// Clear the screen
		pa.background(backgroundColor);
		
		// Draw widgets
		// Widgets decide what to do in response to a draw call
	    for (Widget widget : widgets) {
			if (!widget.hidden) widget.draw();
	    }
	}

    public Button addButton(float[] r, String label, int color1, int color2) {
    	Button newButton = new Button(pa, r, label, color1, color2);
    	widgets.add(newButton);
    	return newButton;
    }	

    public PolyButton addPolyButton(float[] r, String label, int color1, int color2, float[] xx, float[] yy) {
    	PolyButton newPolyButton = new PolyButton(pa, r, label, color1, color2, xx, yy);
    	widgets.add(newPolyButton);
    	return newPolyButton;
    }	
    
    public PlayButton addPlayButton(float[] r) {
    	PlayButton newPlayButton = new PlayButton(pa, r);
    	widgets.add(newPlayButton);
    	return newPlayButton;
    }	

    public PlayButton addPlayButton(double[] r) {
    	float[] temp = new float[r.length];
    	for (int i=0; i < r.length; i++) temp[i] = (float) r[i];
    	return addPlayButton(temp);
    }	    

    public Slider addSlider(float[] r, 
			 float minVal, float maxVal) {
    	Slider newSlider = new Slider(pa, r, minVal, maxVal);
    	widgets.add(newSlider);
   	    return newSlider;
   }	    

    public Slider addSlider(double[] r, 
 			 float minVal, float maxVal) {
    	float[] temp = new float[r.length];
    	for (int i=0; i < r.length; i++) temp[i] = (float) r[i];
    	return addSlider(temp, minVal, maxVal);
    }	    

    public Plot addPlot(float[] r, double[] xData, double[] yData) {
    	Plot newPlot = new Plot(pa, r, xData, yData);
    	widgets.add(newPlot);
    	return newPlot;
    }	

    public Plot addPlot(double[] r, double[] xData, double[] yData) {
    	float[] temp = new float[r.length];
    	for (int i=0; i < r.length; i++) temp[i] = (float) r[i];
    	return addPlot(temp, xData, yData);
    }	    

    public PColor addPColor(float[] r, double[] xData, double[] yData, double[][] data) {
    	PColor newPColor = new PColor(pa, r, xData, yData, data);
    	widgets.add(newPColor);
    	return newPColor;
    }	

    public PColor addPColor(double[] r, double[] xData, double[] yData, double[][] data) {
    	float[] temp = new float[r.length];
    	for (int i=0; i < r.length; i++) temp[i] = (float) r[i];
    	return addPColor(temp, xData, yData, data);
    }	    

    public PColor addPColor(double[] r, double[][] data) {
    	float[] temp = new float[r.length];
    	for (int i=0; i < r.length; i++) temp[i] = (float) r[i];
    	double[] yData = new double[data.length];
    	for (int i=0; i < data.length; i++) yData[i] = (double) i;
    	double[] xData = new double[data[0].length];
    	for (int i=0; i < data[0].length; i++) xData[i] = (double) i;
    	return addPColor(temp, xData, yData, data);
    }	    
    
    
	public void mousePressed() {
		// Informs widgets that the mouse button has been pressed
		// while the mouse was over the widget
	    for (Widget widget : widgets) {
			if (widget.over()) widget.mousePressed();
	    }
	}
		
	public void mouseClicked() {
		// Informs widgets that the mouse button has been clicked
		// while the mouse was over the widget
	    for (Widget widget : widgets) {
			if (widget.over()) widget.mouseClicked();
	    }
	}
	
	public void mouseDragged() {
		// Informs widgets that the mouse button has been clicked
		// while the mouse was over the widget
	    for (Widget widget : widgets) {
			if (widget.over()) widget.mouseDragged();
	    }
	}

	public void mouseMoved() {
		// Informs widgets that the mouse has been moved
	    for (Widget widget : widgets) {
			if (widget.over()) widget.mouseMoved();
	    }
	}

	public void mouseReleased() {
		// Informs widgets that the mouse has been moved
	    for (Widget widget : widgets) {
			if (widget.over()) widget.mouseReleased();
	    }
	}

	public void keyPressed() {
		// Informs widgets that the mouse button has been pressed
		// while the mouse was over the widget
	    for (Widget widget : widgets) {
			if (widget.over()) widget.keyPressed();
	    }
	}
		
}

